#ifndef _GOVT_TEAM_HPP_
#define _GOVT_TEAM_HPP_
/*******************************************************************************
 ** Name: team.hpp                                                            **
 ** Description: Basic Team and Formation support                             **
 **                                                                           **
 ** Open Source Initiative (OSI) Approved License                             **
 **                                                                           **
 ** The contents of this file are subject to the terms of the                 **
 ** Common Development and Distribution License, Version 1.0 only             **
 ** (the "License").  You may not use this file except in compliance          **
 ** with the License.                                                         **
 **                                                                           **
 ** You can find a copy of the license in the LICENSE file within             **
 ** this distribution or at $WIKI/display/ODS/License-software.              **
 ** Software distributed under the License is distributed on an "AS IS"       **
 ** basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.           **
 ** See the License for the specific language governing permissions           **
 ** and limitations under the License.                                        **
 **                                                                           **
 ** When distributing Covered Code, include this CDDL header in each          **
 ** file and include the License file at $GAME_DIR/LICENSE.                   **
 ** If applicable, add the following below this header, with the indicated    **
 ** fields enclosed by brackets "[]" replaced with your own identifying       **
 ** information: Portions Copyright [yyyy] [name of copyright owner]          **
 **                                                                           **
 ** Copyright (c) 2009-2012 Open Design Strategies, LLC                       **
 ** All rights reserved.                                                      **
 ******************************************************************************/
// $HeadURL$
// Modified $Date$ by $Author$
// $Id$

//     default                       aegis
//     [fl ][fc ][fr ][   ][   ]     [ffl][fl ][fc  ][fr ][ffr]
//     [cl ][cc ][cr ][   ][   ]     [   ][cl ][cc  ][cr ][   ]
//     [bl ][bc ][br ][   ][   ]     [   ][   ][bc  ][   ][   ]
//     [   ][   ][   ][   ][   ]     [   ][   ][    ][   ][   ]
//     [   ][   ][   ][   ][   ]     [   ][   ][    ][   ][   ]
//
//     tower                         snare
//     [   ][   ][fc ][   ][   ]     [ffl][   ][   ][   ][ffr]
//     [   ][cl ][cc ][cr ][   ]     [fl ][   ][   ][   ][fr ]
//     [fbl][bl ][bc ][br ][fbr]     [   ][cl ][cc ][cr ][   ]
//     [   ][   ][   ][   ][   ]     [   ][   ][bc ][   ][   ]
//     [   ][   ][   ][   ][   ]     [   ][   ][   ][   ][   ]
//
//     point						wedge
//     [   ][fl ][fc ][fr ][   ]	[   ][   ][fc ][   ][   ]
//     [ffl][   ][cf ][   ][ffr]	[   ][fl ][   ][fr ][   ]
//     [   ][   ][cc ][   ][   ]	[cl ][   ][cc ][   ][cr ]
//     [   ][   ][cb ][   ][   ]	[bl ][   ][   ][   ][br ]
//     [   ][   ][cfb][   ][   ]	[   ][   ][bc ][  ][   ]
//
//		banana
//		[   ][   ][fc ][   ][   ]
//		[   ][cfl][cfc][cfr][   ]
//		[   ][ccl][ccc][ccr][   ]
//		[   ][bl ][   ][br ][   ]
//		[   ][   ][   ][   ][   ]

#include "character.hpp"

const int MAX_TEAM_MEMBERS = 9;

enum class TeamPosition : uint8_t
{
	fl,fc,fr,ffl,ffr,fbl, fbr,
	cl,cc,cr,cf,cb,cfb,cfl,cfc,cfr,ccl,ccc,ccr,
	bl,bc,br,
	empty
};

const TeamPosition FormationDefault[5][5] =
{
		{TeamPosition::fl, TeamPosition::fc, TeamPosition::fr, TeamPosition::empty, TeamPosition::empty},
		{TeamPosition::cl, TeamPosition::cc, TeamPosition::cr, TeamPosition::empty, TeamPosition::empty},
		{TeamPosition::bl, TeamPosition::bc, TeamPosition::br, TeamPosition::empty, TeamPosition::empty},
		{TeamPosition::empty, TeamPosition::empty,TeamPosition::empty,TeamPosition::empty,TeamPosition::empty},
		{TeamPosition::empty, TeamPosition::empty,TeamPosition::empty,TeamPosition::empty,TeamPosition::empty}
};

const TeamPosition FormationAegis[5][5] =
{
		{TeamPosition::ffl, TeamPosition::fl, TeamPosition::fc, TeamPosition::fr, TeamPosition::ffr},
		{TeamPosition::empty,TeamPosition::cl, TeamPosition::cc, TeamPosition::cr, TeamPosition::empty},
		{TeamPosition::empty,TeamPosition::empty,TeamPosition::bc,TeamPosition::empty,TeamPosition::empty},
		{TeamPosition::empty,TeamPosition::empty,TeamPosition::empty,TeamPosition::empty,TeamPosition::empty},
		{TeamPosition::empty,TeamPosition::empty,TeamPosition::empty,TeamPosition::empty,TeamPosition::empty}
};

const TeamPosition FormationBanana[5][5] =
{
		{TeamPosition::empty,TeamPosition::empty,TeamPosition::fc,TeamPosition::empty,TeamPosition::empty},
		{TeamPosition::empty,TeamPosition::cfl, TeamPosition::cfc, TeamPosition::cfr,TeamPosition::empty},
		{TeamPosition::empty,TeamPosition::ccl, TeamPosition::ccc, TeamPosition::ccr,TeamPosition::empty},
		{TeamPosition::empty,TeamPosition::bl, TeamPosition::empty, TeamPosition::br, TeamPosition::empty},
		{TeamPosition::empty,TeamPosition::empty,TeamPosition::empty,TeamPosition::empty,TeamPosition::empty}
};

const TeamPosition FormationWedge[5][5] =
{
		{TeamPosition::empty,TeamPosition::empty,TeamPosition::fc,TeamPosition::empty,TeamPosition::empty},
		{TeamPosition::empty,TeamPosition::fl,TeamPosition::empty,TeamPosition::fr,TeamPosition::empty},
		{TeamPosition::cl,TeamPosition::empty, TeamPosition::cc,TeamPosition::empty,TeamPosition::cr},
		{TeamPosition::bl,TeamPosition::empty,TeamPosition::empty,TeamPosition::empty,TeamPosition::br},
		{TeamPosition::empty,TeamPosition::empty,TeamPosition::bc,TeamPosition::empty,TeamPosition::empty}
};

const TeamPosition FormationPoint[5][5] =
{
		{TeamPosition::empty,TeamPosition::fl,TeamPosition::fc,TeamPosition::fr,TeamPosition::empty},
		{TeamPosition::ffl,TeamPosition::empty,TeamPosition::cf,TeamPosition::empty,TeamPosition::ffr},
		{TeamPosition::empty,TeamPosition::empty,TeamPosition::cc,TeamPosition::empty,TeamPosition::empty},
		{TeamPosition::empty,TeamPosition::empty,TeamPosition::cb,TeamPosition::empty,TeamPosition::empty},
		{TeamPosition::empty,TeamPosition::empty,TeamPosition::cfb,TeamPosition::empty,TeamPosition::empty}
};

const TeamPosition FormationTower[5][5] =
{
		{TeamPosition::empty,TeamPosition::empty,TeamPosition::fc,TeamPosition::empty,TeamPosition::empty},
		{TeamPosition::empty,TeamPosition::cl,TeamPosition::cc,TeamPosition::cr,TeamPosition::empty},
		{TeamPosition::fbl, TeamPosition::bl, TeamPosition::bc, TeamPosition::br, TeamPosition::fbr},
		{TeamPosition::empty,TeamPosition::empty,TeamPosition::empty,TeamPosition::empty,TeamPosition::empty},
		{TeamPosition::empty,TeamPosition::empty,TeamPosition::empty,TeamPosition::empty,TeamPosition::empty}
};

const TeamPosition FormationSnare[5][5] =
{
		{TeamPosition::ffl,TeamPosition::empty,TeamPosition::empty,TeamPosition::empty,TeamPosition::ffr},
		{TeamPosition::fl,TeamPosition::empty,TeamPosition::empty,TeamPosition::empty,TeamPosition::fr},
		{TeamPosition::empty,TeamPosition::cl,TeamPosition::cc,TeamPosition::cr,TeamPosition::empty},
		{TeamPosition::empty,TeamPosition::empty,TeamPosition::bc,TeamPosition::empty,TeamPosition::empty},
		{TeamPosition::empty,TeamPosition::empty,TeamPosition::empty,TeamPosition::empty,TeamPosition::empty}
};

enum class Formation
{
	Default, Aegis, Tower, Snare,
	Point, Wedge, Banana
};

enum class TeamLootType
{
	Split, Leader, RoundRobin
};

class Team
{
public:
	SMART_PTR_DECL(Team);
	static pointer Create(const std::string & n) {
		return boost::make_shared<Team>(n);
	}
	struct Member
	{
		TeamPosition	pos;
		Character::pointer	member;
	};

	Team();
	Team(const std::string & n);
	~Team() { // is this needed?
		//delete _channel;	// if we allocated channel it will go out of scope here
	}

	void	AddMember(Character::pointer m);
	void	RemoveMember(Character::pointer m);
	void	SetFormation(Formation f);
	void 	Leader(Character::pointer l) { _leader = l; }
	void	SendToTeamChannel(const char * m);
	void	AssignPosition(const std::string &c, TeamPosition t);
	void	SetLootType(TeamLootType t)
	{
		_loot = t;
		switch(_loot)
		{
		case TeamLootType::Split:
			SendToTeamChannel("Loot type changed to SPLIT");
			break;
		case TeamLootType::Leader:
			SendToTeamChannel("Loot type changed to LEADER");
			break;
		case TeamLootType::RoundRobin:
			SendToTeamChannel("Loot type changed to ROUND ROBIN");
			break;
		}
	}

	uint8_t	ACL() {
		std::vector<Member>::iterator i;
		uint8_t	acl = 0, num = 0;
		for(i = _members.begin(); i != _members.end(); ++i)
		{
			acl += (uint8_t)i->member->Level();
			++num;
		}
		return ((uint8_t)acl/num);
	}

	Character::pointer Leader() const { return _leader; }
	const size_t HeadCount() const { return _members.size(); }


private:
	void	_assign_member_positions();
	bool	_is_position_taken(TeamPosition);
	TeamPosition _get_next_available_position(const TeamPosition [5][5],int&,int&);

	std::vector<Member>	_members;
	Character::pointer			_leader;
	Formation			_formation;
	boost::shared_ptr<channel>	_channel;
	TeamLootType		_loot;
};



#endif /* TEAM_HPP_ */
